//  
// @Author: xzw
// @Description:工具文件
// @Version: 1.0.0
// @Date: 2021/3/5 上午9:18
// @Copyright: MIN-Group；国家重大科技基础设施——未来网络北大实验室；深圳市信息论与未来网络重点实验室
// 

const sm2 = require("./sm2/external")
const com = require("../common")
const crypto = require("../crypto")

//定义pem格式到公私钥的转换
function FromPemToPubkey() {

}

function PubkeyToPem() {

}

function FromPemToPrikey() {

}

function PrikeyToPem() {

}

//
// 通过给定的公钥结构体返回对应的编码结果和使用的算法
//
// @Description:
// @param pub interface{}
// @return sec.PublicKeyAlgorithm, []byte
//
function MarshalPublicKey(pub) {
    const sec = require("../crypto")
	if(pub instanceof sec.PublicKey) {
        console.log("开始getBytes解析")
		return [com.PublicKeyAlgorithm.SM2, pub.GetBytes()]
	}
	return [com.PublicKeyAlgorithm.SM2, null]
}

//
// 通过给定的私钥结构体返回对应的编码和使用的算法
//
// @Description:
// @param pub interface{}
// @return sec.PublicKeyAlgorithm, []byte
//
function MarshalPrivateKey(pri) {
    const sec = require("../crypto")
    //let p = new sm2.Sm2PrivateKey()
    if(pri instanceof sec.PrivateKey || pri instanceof sm2.Sm2PrivateKey) {
        console.log("开始getBytes解析")
		return [com.PublicKeyAlgorithm.SM2, pri.GetBytes()]
	}
	return [com.PublicKeyAlgorithm.SM2, null]
}

//
// 通过给定的私钥类型和编码返回对应的私钥结构体
//
// @Description:
// @param priByte []byte
// @param algo com.PublicKeyAlgorithm
// @return sec.PrivateKey
// @return error
//
function UnMarshalPrivateKey(priByte, algo) {
	if (priByte == null || priByte.length == 0) {
        console.log("priByte is null")
		return [null, null]
	}

	switch (algo) {
	case com.PublicKeyAlgorithm.SM2:
        const sm2 = require("./sm2/external")
		let p = new sm2.Sm2PrivateKey
		let err = p.SetBytes(priByte)
		if (err != null) {
			return [null, err]
		}
        const crypto = require("../crypto")
	    var res = new crypto.PrivateKey(p.PrivateKey)
		return [res, null]
	}
    console.log("私钥解析fail")
	return [null, null]
}

//
// 通过给定的公钥类型和编码返回对应的公钥结构体
//
// @Description:
// @param pubByte []byte
// @param algo com.PublicKeyAlgorithm
// @return sec.PublicKey
// @return error
//
function UnMarshalPublicKey(pubByte, algo) {
	if (pubByte == null || pubByte.length == 0) {
	    console.log("pubByte is null")
		return [null, null]
	}
	switch (algo) {
	case com.PublicKeyAlgorithm.SM2:
        const sm2 = require("./sm2/external")
		let p = new sm2.Sm2PublicKey
		let err = p.SetBytes(pubByte)
		if (err != null) {
			return [null, err]
		}
        const crypto = require("../crypto")
		var res = new crypto.PublicKey(p.PublicKey)
		return [res, null]
	}
	console.log("公钥解析fail")
	return [null, null]
}

//
// 字符串转为字节数组
//
// @Description:
// @param str string
// @return []bytes
//
function Str2Bytes(str) {
    if(typeof str != 'string') {
        return new Error("所需转成字节数组的变量不是字符串类型").message;
    }
    var bytes = new Array();  
    var len, c;  
    len = str.length;  
    for(var i = 0; i < len; i++) {  
        c = str.charCodeAt(i);  
        if(c >= 0x010000 && c <= 0x10FFFF) {  
            bytes.push(((c >> 18) & 0x07) | 0xF0);  
            bytes.push(((c >> 12) & 0x3F) | 0x80);  
            bytes.push(((c >> 6) & 0x3F) | 0x80);  
            bytes.push((c & 0x3F) | 0x80);  
        } else if(c >= 0x000800 && c <= 0x00FFFF) {  
            bytes.push(((c >> 12) & 0x0F) | 0xE0);  
            bytes.push(((c >> 6) & 0x3F) | 0x80);  
            bytes.push((c & 0x3F) | 0x80);  
        } else if(c >= 0x000080 && c <= 0x0007FF) {  
            bytes.push(((c >> 6) & 0x1F) | 0xC0);  
            bytes.push((c & 0x3F) | 0x80);  
        } else {  
            bytes.push(c & 0xFF);  
        }  
    }  
    return bytes; 
}

//
// 字节数组转为字符串
//
// @Description:
// @param arr []bytes
// @return string
//
function Bytes2Str(arr) {
    if(arr === null|| arr === undefined){
        return ""
    }
    if(typeof arr === 'string') {
        return arr;
    }
    var str = '',
        _arr = arr;
    for(var i = 0; i < _arr.length; i++) {
        var one = _arr[i].toString(2),
            v = one.match(/^1+?(?=0)/);
        if(v && one.length == 8) {
            var bytesLength = v[0].length;
            var store = _arr[i].toString(2).slice(7 - bytesLength);
            for(var st = 1; st < bytesLength; st++) {
                store += _arr[st + i].toString(2).slice(2);
            }
            str += String.fromCharCode(parseInt(store, 2));
            i += bytesLength - 1;
        } else {
            str += String.fromCharCode(_arr[i]);
        }
    }
    return str;
}

module.exports = {
    MarshalPublicKey: MarshalPublicKey,
    MarshalPrivateKey: MarshalPrivateKey,
	UnMarshalPrivateKey: UnMarshalPrivateKey,
    UnMarshalPublicKey: UnMarshalPublicKey,
    Str2Bytes: Str2Bytes,
    Bytes2Str: Bytes2Str
}